package netty.dubbo.server.registry;

import netty.dubbo.api.ZkConstant;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;

import java.nio.charset.StandardCharsets;

/**
 * @author: 程序员七哥
 * @date: 2021-12-19
 * @description: 定义 zk 注册中心实现类
 */
public class ZkRegistryCenter implements RegistryCenter{

    private CuratorFramework curator;

    // 静态代码块，在类加载时执行
    {
        // 创建 zk 客户端实例
        curator = CuratorFrameworkFactory.builder()
                .connectString(ZkConstant.ZK_CLUSTER)
                // 连接超时时间，默认 15 秒
                .connectionTimeoutMs(10000)
                // 会话超时时间，默认 60 秒
                .sessionTimeoutMs(3000)
                // 设置重试机制，没间隔 1 秒重试 1 次，最多 10 次
                .retryPolicy(new ExponentialBackoffRetry(1000,10))
                .build();
        curator.start();
    }

    @Override
    public void register(String serviceName, String serviceAddress) throws Exception {
        // 创建 zk 服务节点名称
        String servicePath = ZkConstant.ZK_DUBBO_ROOT_PATH + "/" + serviceName;
        // 若节点不存在，则创建
        if (curator.checkExists().forPath(servicePath) == null) {
            // 创建服务名称的持久节点
            curator.create()
                    // 如果父节点不存在，则创建
                    .creatingParentsIfNeeded()
                    .withMode(CreateMode.PERSISTENT)
                    .forPath(servicePath,"空数据占位".getBytes(StandardCharsets.UTF_8));

        }
        // 创建服务名称下一级节点，服务提供者的 ip:port
        String addressPath = servicePath + "/" + serviceAddress;
        // 创建ip+port的临时节点
        final String nodeName = curator.create()
                .creatingParentsIfNeeded()
                // 设置为临时节点
                .withMode(CreateMode.EPHEMERAL)
                .forPath(addressPath, "空数据占位".getBytes(StandardCharsets.UTF_8));

        System.out.println("服务提供者主机节点注册完成： " + nodeName);


    }
}
